package com.winning.pmph.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.winning.pmph.entity.*;
import com.winning.pmph.mapper.KnowledgeUnitMapper;
import com.winning.pmph.utils.Const;
import com.winning.pmph.utils.PMPHAppUtil;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Transactional
public class KnowledgeUnitService extends ServiceImpl<KnowledgeUnitMapper, KnowledgeUnit> {
    @Resource
    private KnowledgeUnitMapper knowledgeUnitMapper;
    @Resource
    private BookService bookService;
    @Resource
    private TaskItemService taskItemService;
    @Resource
    private TempKnowledgeService tempKnowledgeService;
    @Resource
    private TempKnowledgeFieldService tempKnowledgeFieldService;
    @Resource
    private KnowledgeLibFieldService knowledgeLibFieldService;
    @Resource
    private ReleasedKnowledgeService releasedKnowledgeService;
    @Resource
    private KnowledgeUnitParseKnowledgeTaskService knowledgeUnitParseKnowledgeTaskService;
    @Resource
    private KnowledgeUnitParseKnowledgeTaskItemService knowledgeUnitParseKnowledgeTaskItemService;
    @Resource
    private KnowledgeUnitFieldService knowledgeUnitFieldService;

    /**
     * 保存并标注, 返回本次知识单元从 temp 到 released 数据;
     * @param knowledgeUnitList
     * @param bookId
     * @return
     */
    public List<KnowledgeUnit> insertListAndReleased(List<KnowledgeUnit> knowledgeUnitList, String bookId, String markedRate) {
        saveBatch(knowledgeUnitList);
        // 修改 提取进度;
        bookService.update(Wrappers.lambdaUpdate(Book.class)
                .set(Book::getMarkedRate, markedRate)
                .eq(Book::getId, bookId));
        // 查询目前暂存的数据;
        List<KnowledgeUnit> tempKnowledgeUnitList = lambdaQuery().eq(KnowledgeUnit::getBookId, bookId)
                .eq(KnowledgeUnit::getStatus, Const.KNOWLEDGE_UNIT_STATUS_TEMP).list();
        update(Wrappers.lambdaUpdate(KnowledgeUnit.class)
                .set(KnowledgeUnit::getStatus, Const.KNOWLEDGE_UNIT_STATUS_RELEASE)
                .eq(KnowledgeUnit::getBookId, bookId));
        tempKnowledgeUnitList.forEach(knowledgeUnit -> knowledgeUnit.setStatus(Const.KNOWLEDGE_UNIT_STATUS_RELEASE));
        return tempKnowledgeUnitList;
    }

    public void insertKnowledge(Knowledge knowledge, List<KnowledgeLibField> knowledgeLibFieldList, TaskItem taskItem) {
        // 准备任务历史对象;
        KnowledgeUnitParseKnowledgeTask history = new KnowledgeUnitParseKnowledgeTask();
        history.setTaskId(taskItem.getTaskId());
        history.setStatus(KnowledgeUnitParseKnowledgeTask.STATUS_FINISHED);
        knowledgeUnitParseKnowledgeTaskService.save(history);
        // 保存知识;
        submitParse2Knowledge(knowledge, taskItem);
        // 准备子任务历史对象;
        KnowledgeUnitParseKnowledgeTaskItem itemHistory = new KnowledgeUnitParseKnowledgeTaskItem();
        itemHistory.setKnowledgeUnitId(knowledge.getKnowledgeUnitId());
        itemHistory.setKnowledgeUnitParseKnowledgeTaskId(history.getId());
        itemHistory.setTaskItemId(taskItem.getId());
        knowledgeUnitParseKnowledgeTaskItemService.save(itemHistory);
        // 保存字段对应关系;
        knowledge.getKnowledgeUnitFieldList().forEach(item -> item.setKnowledgeUnitParseKnowledgeTaskId(history.getId()));
        knowledgeUnitFieldService.saveBatch(knowledge.getKnowledgeUnitFieldList());
        // 修改知识库字段 synonym;
        knowledgeLibFieldService.updateBatchById(knowledgeLibFieldList);
    }

    public void submitParse2Knowledge(Knowledge knowledge, TaskItem taskItem) {
        // 修改知识单元绑定知识ID;
        update(Wrappers.lambdaUpdate(KnowledgeUnit.class)
                .set(KnowledgeUnit::getKnowledgeId, knowledge.getId())
                .eq(KnowledgeUnit::getId, knowledge.getKnowledgeUnitId()));
        // 新增子任务;
        taskItem.setKnowledgeId(knowledge.getId());
        taskItem.setName(knowledge.getName());
        if (Objects.nonNull(releasedKnowledgeService.getById(knowledge.getId()))){
            taskItem.setType(TaskItem.TYPE_EDIT_KNOWLEDGE_UNIT);    // 修订_素材;
            tempKnowledgeService.removeById(knowledge.getId());
        }
        else {
            taskItem.setType(TaskItem.TYPE_TASK_EDITOR_CREATE_KNOWLEDGE_UNIT);  // 非自建_素材;
        }
        taskItem.setEditor(PMPHAppUtil.getCurrentUserEnName());
        taskItem.setStatus(TaskItem.STATUS_NOT_COMMIT);
        taskItemService.save(taskItem);
        // 新增知识;
        tempKnowledgeService.save(JSON.parseObject(JSON.toJSONString(knowledge), TempKnowledge.class));
        for (KnowledgeField knowledgeField : knowledge.getKnowledgeFieldList()) {
            // 知识字段名称为空, 说明是知识单元字段, 废弃;
            if (StringUtils.isNotEmpty(knowledgeField.getName())) {
                TempKnowledgeField tempKnowledgeField = JSON.parseObject(JSON.toJSONString(knowledgeField), TempKnowledgeField.class);
                tempKnowledgeFieldService.saveOrUpdate(tempKnowledgeField);
            }
        }
    }

    public void insertKnowledgeList(List<Knowledge> knowledgeList, List<KnowledgeLibField> knowledgeLibFieldList, TaskItem taskItem) {
        // 先删除历史对象;
        deleteTaskByKnowledgeList(knowledgeList);
        // 准备任务历史对象;
        KnowledgeUnitParseKnowledgeTask history = new KnowledgeUnitParseKnowledgeTask();
        history.setTaskId(taskItem.getTaskId());
        history.setType(1);
        history.setStatus(KnowledgeUnitParseKnowledgeTask.STATUS_FINISHED);
        knowledgeUnitParseKnowledgeTaskService.save(history);
        for (Knowledge knowledge : knowledgeList) {
            prepareKnowledge(knowledge);
            TaskItem taskItemBak = JSON.parseObject(JSON.toJSONString(taskItem), TaskItem.class);
            submitParse2Knowledge(knowledge, taskItemBak);
            // 准备子任务历史对象;
            KnowledgeUnitParseKnowledgeTaskItem itemHistory = new KnowledgeUnitParseKnowledgeTaskItem();
            itemHistory.setKnowledgeUnitId(knowledge.getKnowledgeUnitId());
            itemHistory.setKnowledgeUnitParseKnowledgeTaskId(history.getId());
            itemHistory.setTaskItemId(taskItemBak.getId());
            knowledgeUnitParseKnowledgeTaskItemService.saveOrUpdate(itemHistory);
            // 保存字段对应关系;
            knowledge.getKnowledgeUnitFieldList().forEach(item -> {
                item.setKnowledgeUnitParseKnowledgeTaskId(history.getId());
                item.setKnowledgeUnitId(knowledge.getKnowledgeUnitId());
            });
            knowledgeUnitFieldService.saveBatch(knowledge.getKnowledgeUnitFieldList());
        }
        // 修改知识库字段 synonym;
        knowledgeLibFieldService.updateBatchById(knowledgeLibFieldList);
    }

    private void deleteTaskByKnowledgeList(List<Knowledge> knowledgeList) {
        String historyId = knowledgeList.stream()
                .flatMap(item -> item.getKnowledgeUnitFieldList().stream()).findAny().get().getKnowledgeUnitParseKnowledgeTaskId();
        if (StringUtils.isNotEmpty(historyId)) {
            deleteTask(historyId);
        }
    }

    public void saveEditingTask(List<Knowledge> knowledgeList, List<KnowledgeLibField> knowledgeLibFieldList, TaskItem taskItem) {
        // 先删除历史对象;
        deleteTaskByKnowledgeList(knowledgeList);
        // 准备任务历史对象;
        KnowledgeUnitParseKnowledgeTask history = new KnowledgeUnitParseKnowledgeTask();
        history.setTaskId(taskItem.getTaskId());
        history.setType(1);
        history.setStatus(KnowledgeUnitParseKnowledgeTask.STATUS_EDITING);
        history.setRemark(taskItem.getRemark());
        knowledgeUnitParseKnowledgeTaskService.save(history);
        for (Knowledge knowledge : knowledgeList) {
            // 修改知识单元绑定知识ID;
            update(Wrappers.lambdaUpdate(KnowledgeUnit.class)
                    .set(KnowledgeUnit::getKnowledgeId, KnowledgeUnit.TASK_EDITING_KID)
                    .eq(KnowledgeUnit::getId, knowledge.getKnowledgeUnitId()));
            // 准备子任务历史对象;
            KnowledgeUnitParseKnowledgeTaskItem itemHistory = new KnowledgeUnitParseKnowledgeTaskItem();
            itemHistory.setKnowledgeUnitId(knowledge.getKnowledgeUnitId());
            itemHistory.setKnowledgeUnitParseKnowledgeTaskId(history.getId());
            knowledgeUnitParseKnowledgeTaskItemService.save(itemHistory);
            // 保存字段对应关系;
            knowledge.getKnowledgeUnitFieldList().forEach(item -> {
                item.setKnowledgeUnitParseKnowledgeTaskId(history.getId());
                item.setKnowledgeUnitId(knowledge.getKnowledgeUnitId());
            });
            knowledgeUnitFieldService.saveBatch(knowledge.getKnowledgeUnitFieldList());
        }
        // 修改知识库字段 synonym;
        knowledgeLibFieldService.updateBatchById(knowledgeLibFieldList);
    }

    public void prepareKnowledge(Knowledge knowledge) {
        // 准备知识字段来源;
        KnowledgeUnit knowledgeUnit = getById(knowledge.getKnowledgeUnitId());
        Book book = bookService.getById(knowledgeUnit.getBookId());
        JSONObject bookSource = new JSONObject();
        bookSource.put("name", book.getName());
        String editionStr = book.getMetadata().getString("Edition");
        int edition = 1;
        try {
            edition = Integer.parseInt(editionStr);
        } catch (NumberFormatException e) {
            log.error("图书: " + book.getName() + book.getIsbn() + ", edition有误");
            e.printStackTrace();
        }
        bookSource.put("edition", "第" + edition + "版");
        bookSource.put("isbn", book.getIsbn());
        // 为保证多个知识单元字段对应一个知识字段, 且保证知识单元字段顺序, 外层遍历知识存储的知识单元字段map;
        // 准备待插入的idx, 动态字段插入(排序)使用;
        // 如果第一个字段设置成动态字段，顺序放到第一个富文本字段之前;
        int insertIdx = 1;
        for (int i = 1; i < knowledge.getKnowledgeFieldList().size(); i++) {
            KnowledgeField knowledgeField = knowledge.getKnowledgeFieldList().get(i);
            if (KnowledgeLibField.FIELD_KIND_RICHEDITOR == knowledgeField.getKind()) {
                break;
            }
            insertIdx = i + 1;
        }
        for (KnowledgeUnitField knowledgeUnitField : knowledge.getKnowledgeUnitFieldList()) {
            String knowledgeUnitFieldName = knowledgeUnitField.getName();
            // 废弃字段
            String knowledgeLibFieldName = StringUtils.defaultIfEmpty(knowledgeUnitField.getKnowledgeLibFieldName(), knowledgeUnitField.getKnowledgeLibFieldNameDefault());
            if (StringUtils.isEmpty(knowledgeLibFieldName)) {
                continue;
            }
            KnowledgeField knowledgeField = null;
            // 固定字段;
            String knowledgeLibFieldId = StringUtils.defaultIfEmpty(knowledgeUnitField.getKnowledgeLibFieldId(), knowledgeUnitField.getKnowledgeLibFieldIdDefault());
            if (StringUtils.isNotEmpty(knowledgeLibFieldId)) {
                knowledgeField = knowledge.getKnowledgeFieldList().stream()
                        .filter(item -> StringUtils.equals(knowledgeLibFieldId, item.getKnowledgeLibFieldId()))
                        .findFirst().get();
            } else {
                // 是否已有相同名称动态字段;
                Optional<KnowledgeField> knowledgeFieldOptional = knowledge.getKnowledgeFieldList().stream()
                        .filter(item -> StringUtils.equals(item.getName(), knowledgeLibFieldName))
                        .findFirst();
                if (knowledgeFieldOptional.isPresent()) {
                    knowledgeField = knowledgeFieldOptional.get();
                } else {
                    knowledgeField = new KnowledgeField();
                    knowledgeField.setKind(KnowledgeLibField.FIELD_KIND_RICHEDITOR);
                    knowledgeField.setName(knowledgeLibFieldName);
                    knowledgeField.setKnowledgeId(knowledge.getId());
                    knowledge.getKnowledgeFieldList().add(insertIdx, knowledgeField);
                }
            }
            // 写入内容到知识字段, 添加自由标签的情况;
            if (StringUtils.equals(Const.KNOWLEDGE_UNIT_CUSTOM_TAG_KEY, knowledgeUnitFieldName)) {
                knowledgeField.setKind(KnowledgeLibField.FIELD_KIND_MULTI_VALUE_INPUT);
                knowledgeField.setProperty(knowledgeUnitField.getContent());
            }
            else {
                String property = StringUtils.isBlank(knowledgeField.getProperty()) ? StringUtils.EMPTY : knowledgeField.getProperty() + System.lineSeparator();
                String knowledgeUnitFieldLine = "<p class=\"knowledgeUnitFieldLabel\">" + knowledgeUnitField.getName() + "</p>" + System.lineSeparator();
                property += knowledgeUnitFieldLine;
                property += knowledgeUnitField.getContent();
                knowledgeField.setProperty(property);
                // 设置知识字段来源;
                if (CollectionUtils.isNotEmpty(knowledgeField.getSource())) {
                    // 当前知识单元是否已有图书isbn;
                    boolean existBookSourceFlag = knowledgeField.getSource().stream()
                            .map(item -> ((Map<String, String>) item).get("isbn"))
                            .anyMatch(bookSource.getString("isbn")::equals);
                    if (!existBookSourceFlag) {
                        knowledgeField.getSource().add(bookSource);
                    }
                } else {
                    JSONArray tmpSource = new JSONArray();
                    tmpSource.add(bookSource);
                    knowledgeField.setSource(tmpSource);
                }
            }
            insertIdx = knowledge.getKnowledgeFieldList().indexOf(knowledgeField) + 1;
        }
        // 经过上述操作, 所有素材字段前面都添加了素材字段标题;
        // 如果首行为素材字段标题, 则说明是此次新增字段内容;
        List<KnowledgeField> insertKnowledgeFieldList = knowledge.getKnowledgeFieldList().stream()
                .filter(item -> item.getKind() == KnowledgeLibField.FIELD_KIND_RICHEDITOR)
                .filter(item -> item.getProperty().startsWith("<p class=\"knowledgeUnitFieldLabel\">"))
                .collect(Collectors.toList());
        for (KnowledgeField knowledgeField : insertKnowledgeFieldList) {
            Element propertyElement = Jsoup.parse(knowledgeField.getProperty()).body();
            // 新增字段内容, 素材标题自动转为 class="h1"
            Elements knowledgeUnitFieldLabelElements = propertyElement.getElementsByClass("knowledgeUnitFieldLabel");
            knowledgeUnitFieldLabelElements.forEach(item -> item.attr("class", "h1"));
            // 如果只有一个素材标题, 则把素材标题去除, 并把所有h标签提升一级;
            if (knowledgeUnitFieldLabelElements.size() == 1) {
                propertyElement.child(0).remove();
                propertyElement.children().stream()
                        .filter(item -> item.tagName().toLowerCase().startsWith("h"))
                        .forEach(item -> item.tagName("h" + (Integer.parseInt(item.tagName().replaceAll("h", "")) + 1)));
            }
            knowledgeField.setProperty(propertyElement.html());
        }
        // 考虑有动态字段参与排序, 所以重新设置id;
        knowledge.getKnowledgeFieldList().forEach(field -> field.setId(IdWorker.getIdStr()));
    }

    public void deleteTask(String taskId) {
        // 任务;
        knowledgeUnitParseKnowledgeTaskService.removeById(taskId);
        // 子任务;
        List<KnowledgeUnitParseKnowledgeTaskItem> knowledgeUnitParseKnowledgeTaskItemList = knowledgeUnitParseKnowledgeTaskItemService.lambdaQuery()
                .eq(KnowledgeUnitParseKnowledgeTaskItem::getKnowledgeUnitParseKnowledgeTaskId, taskId).list();
        for (KnowledgeUnitParseKnowledgeTaskItem knowledgeUnitParseKnowledgeTaskItem : knowledgeUnitParseKnowledgeTaskItemList) {
            // 修改知识单元绑定知识ID;
            update(Wrappers.lambdaUpdate(KnowledgeUnit.class)
                    .set(KnowledgeUnit::getKnowledgeId, StringUtils.EMPTY)
                    .eq(KnowledgeUnit::getId, knowledgeUnitParseKnowledgeTaskItem.getKnowledgeUnitId()));
        }
        knowledgeUnitParseKnowledgeTaskItemService.remove(Wrappers.lambdaQuery(KnowledgeUnitParseKnowledgeTaskItem.class)
                .eq(KnowledgeUnitParseKnowledgeTaskItem::getKnowledgeUnitParseKnowledgeTaskId, taskId));
        // 字段映射;
        knowledgeUnitFieldService.remove(Wrappers.lambdaQuery(KnowledgeUnitField.class)
                .eq(KnowledgeUnitField::getKnowledgeUnitParseKnowledgeTaskId, taskId));
    }

    public void deleteTaskItem(TaskItem taskItem) {
        // 知识单元对应知识id, 清空;
        TempKnowledge tempKnowledge = tempKnowledgeService.getById(taskItem.getKnowledgeId());
        if (StringUtils.isNotEmpty(tempKnowledge.getKnowledgeUnitId())) {
            KnowledgeUnit knowledgeUnit = getById(tempKnowledge.getKnowledgeUnitId());
            update(Wrappers.lambdaUpdate(KnowledgeUnit.class)
                    .set(KnowledgeUnit::getKnowledgeId, StringUtils.EMPTY)
                    .eq(KnowledgeUnit::getKnowledgeId, taskItem.getKnowledgeId()));
            // 知识单元字段;
            knowledgeUnitFieldService.remove(Wrappers.lambdaUpdate(KnowledgeUnitField.class).eq(KnowledgeUnitField::getKnowledgeUnitId, knowledgeUnit.getId()));
            // 知识单元任务, 子任务;
            List<KnowledgeUnitParseKnowledgeTaskItem> list = knowledgeUnitParseKnowledgeTaskItemService.lambdaQuery()
                    .eq(KnowledgeUnitParseKnowledgeTaskItem::getTaskItemId, taskItem.getId()).list();
            if (CollectionUtils.isNotEmpty(list)) {
                knowledgeUnitParseKnowledgeTaskItemService.remove(Wrappers.lambdaUpdate(KnowledgeUnitParseKnowledgeTaskItem.class).eq(KnowledgeUnitParseKnowledgeTaskItem::getTaskItemId, taskItem.getId()));
                // 如果子任务没了, 任务也删除;
                List<KnowledgeUnitParseKnowledgeTaskItem> knowledgeUnitParseKnowledgeTaskItems = knowledgeUnitParseKnowledgeTaskItemService.lambdaQuery().eq(KnowledgeUnitParseKnowledgeTaskItem::getKnowledgeUnitParseKnowledgeTaskId, list.get(0).getKnowledgeUnitParseKnowledgeTaskId()).list();
                if (CollectionUtils.isEmpty(knowledgeUnitParseKnowledgeTaskItems)) {
                    knowledgeUnitParseKnowledgeTaskService.removeById(list.get(0).getKnowledgeUnitParseKnowledgeTaskId());
                }
            }
        }
    }

    public KnowledgeUnit getBeanWithFieldById(String knowledgeUnitId) {
        KnowledgeUnit knowledgeUnit = getById(knowledgeUnitId);
        splitKnowledgeUnit(knowledgeUnit);
        return knowledgeUnit;
    }

    public void splitKnowledgeUnit(KnowledgeUnit knowledgeUnit) {
        LinkedHashMap<String, String> name2ContentMap = Maps.newLinkedHashMap();
        // 获取最大h标签;
        Element body = Jsoup.parse(knowledgeUnit.getContent()).body();
        OptionalInt optionalInt = body.getAllElements().stream()
                .map(ele -> ele.tagName().toLowerCase())
                .filter(tagName -> tagName.startsWith("h"))
                .map(tagName -> tagName.replaceAll("\\D", ""))
                .mapToInt(Integer::parseInt).min();
        if (optionalInt.isPresent()) {
            // 按照最大h标签进行切割;
            String topTagName = "h" + optionalInt.getAsInt();
            String selfContent = "";
            String crtTitle = "";
            for (Element child : body.children()) {
                if (StringUtils.equals(topTagName, child.tagName().toLowerCase())) {
                    crtTitle = parseCatalogName2KnowledgeFieldName(child.text());
                    name2ContentMap.put(crtTitle, "");
                }
                else if (StringUtils.isEmpty(crtTitle)){
                    selfContent += child.outerHtml();
                    if (StringUtils.isNotEmpty(selfContent)) {
                        name2ContentMap.put(Const.KNOWLEDGE_UNIT_FIELD_SELF, selfContent);
                    }
                }
                else {
                    name2ContentMap.put(crtTitle, name2ContentMap.get(crtTitle) + child.outerHtml());
                }
            }
        }
        // 没有h标签, 全部内容为无标题字段内容;
        else {
            name2ContentMap.put(Const.KNOWLEDGE_UNIT_FIELD_SELF, knowledgeUnit.getContent());
        }
        // 内容map, 重新计算 h 标签 转为 p class=h
        for (String key : name2ContentMap.keySet()) {
            String content = name2ContentMap.get(key);
            Element itemBody = Jsoup.parse(content).body();
            // 例如 如果段落内只有 h3, h5, h8, 则数组存储[3,  5, 8], 应该转为 p class = h2, h3, h4
            int[] hArray = itemBody.getAllElements().stream()
                    .map(ele -> ele.tagName().toLowerCase())
                    .filter(tagName -> tagName.startsWith("h"))
                    .map(tagName -> tagName.replaceAll("\\D", ""))
                    .mapToInt(Integer::parseInt).sorted()
                    .distinct().toArray();
            for (int i = 0; i < hArray.length; i++) {
                String tagName = "h" + hArray[i];
                String className = "h" + (i + 2);
                itemBody.getElementsByTag(tagName)
                        .forEach(item -> item.tagName("p").addClass(className));
            }
            name2ContentMap.put(key, itemBody.html());
        }
        // 组装 knowledgeUnitFieldList
        List<KnowledgeUnitField> knowledgeUnitFieldList = Lists.newArrayList();
        for (String name : name2ContentMap.keySet()) {
            KnowledgeUnitField knowledgeUnitField = new KnowledgeUnitField();
            knowledgeUnitField.setKnowledgeUnitId(knowledgeUnit.getId());
            knowledgeUnitField.setName(name);
            knowledgeUnitField.setContent(name2ContentMap.get(name));
            knowledgeUnitFieldList.add(knowledgeUnitField);
        }
        knowledgeUnit.setKnowledgeUnitFieldList(knowledgeUnitFieldList);
    }

    public static String parseCatalogName2KnowledgeFieldName(String catalogName) {
        // 去除空格;
        String name = catalogName.trim();
        // 去除[]【】
        name = name.replaceAll("\\[?]?【?】?", "");
        // 去除开头第一章... 第一节...
        name = name.replaceAll("^第[一二三四五六七八九十]+[章节]", "");
        // 去除开头 一、 二、 三... (一) (二) (三)... 1. (1)
        name = name.replaceAll("^[\\(\\（]?[一二三四五六七八九十0123456789]+[\\)\\）\\.]?[\\.\\、]?", "");
        // 去除结尾:
        name = name.replaceAll("[:：]$", "");
        // 去除开头病例1 病例一 病例2 ...
        name = name.replaceAll("^病例[一二三四五六七八九十0123456789]+", "");
        // 去除以① ... 开头
        name = name.replaceAll("^[①②③④⑤⑥⑦⑧⑨⑩]", "");
        return name.trim();
    }
}
